<template>
  <div>
    <!-- 顶部导航栏 -->
    <!-- <el-header class="custom-header">
      <div class="header-left">
        <span class="logo-title">作物标准象与象差知识库系统</span>
      </div>
 
    </el-header> -->
    
    <!-- 分类导航 -->
    <div>
      <el-menu 
        :default-active="activeIndex" 
        class="custom-menu" 
        mode="horizontal"
        @select="handleSelect">
        <el-menu-item index="1">首页</el-menu-item>
        <el-menu-item index="2">标准象百科</el-menu-item>
        <el-menu-item index="3">象差百科</el-menu-item>
        <el-menu-item index="4">知识检索</el-menu-item>
        <el-menu-item index="5" @click="handleSelect(5)">问答专区</el-menu-item>
      </el-menu>
    </div>
    
    <!-- 搜索区域 -->
    <div class="search-section">
      <div class="headline">知识检索 - 作物知识图谱</div>
      
      <div class="search-bar">
        <el-input 
          v-model="searchKeyword" 
          placeholder="请输入关键词"
          class="search-input"
          clearable>
          <template #append>
            <el-button type="primary" @click="onSearch" style="font-size:20px;color:#409EFF">搜索</el-button>
          </template>
        </el-input>
      </div>
      
      <div class="hot-words">
        热门搜索：
        <el-link type="primary" @click="setKeyword('小麦赤霉病')">小麦赤霉病</el-link>
        <el-link type="primary" @click="setKeyword('玉米褐斑病')">玉米褐斑病</el-link>
      </div>
    </div>

    <!-- 知识图谱主要区域 - 左右布局 -->
    <div class="knowledge-graph-container">
      <!-- 顶部工具栏 -->
      <div class="graph-toolbar">
        <div class="toolbar-left">
          <div class="search-container">
            <el-autocomplete
              v-model="graphSearchKeyword"
              :fetch-suggestions="querySearchSuggestions"
              placeholder="搜索作物或品种（如：小麦、保麦）"
              class="search-input"
              @select="handleSuggestionSelect"
              @keyup.enter="handleGraphSearch"
              :debounce="300"
              clearable
            >
              <template #prefix>
                <el-icon><Search /></el-icon>
              </template>
              <template #default="{ item }">
                <div class="suggestion-item">
                  <div class="suggestion-main">
                    <span class="suggestion-name">{{ item.name }}</span>
                    <el-tag :type="getSuggestionTagType(item.type)" size="small">
                      {{ getSuggestionTypeLabel(item.type) }}
                    </el-tag>
                  </div>
                  <div class="suggestion-desc">{{ item.description }}</div>
                </div>
              </template>
            </el-autocomplete>
            <el-button type="primary" @click="handleGraphSearch" :loading="searching">
              图谱搜索
            </el-button>
          </div>
        </div>
        
        <div class="toolbar-right">
          <el-button @click="toggleLayoutLock" :type="layoutLocked ? 'success' : 'warning'" size="small">
            <el-icon><Lock v-if="layoutLocked" /><Unlock v-else /></el-icon>
            {{ layoutLocked ? '布局已锁定' : '布局已解锁' }}
          </el-button>
          <el-button @click="resetGraph" type="info" size="small">
            重置图谱
          </el-button>
          <el-button @click="collapseAllNodes" type="warning" size="small">
            收缩所有
          </el-button>
        </div>
      </div>

      <!-- 图例 -->
      <div class="graph-legend">
        <div class="legend-left">
          <div class="legend-item">
            <div class="legend-dot crop"></div>
            <span>作物</span>
          </div>
          <div class="legend-item">
            <div class="legend-dot type"></div>
            <span>类型</span>
          </div>
          <div class="legend-item">
            <div class="legend-dot variety"></div>
            <span>品种</span>
          </div>
          <div class="legend-item">
            <div class="legend-dot disease"></div>
            <span>病害</span>
          </div>
          <div class="legend-item">
            <div class="legend-dot pest"></div>
            <span>虫害</span>
          </div>
          <div class="legend-item">
            <div class="legend-dot stress"></div>
            <span>非生物胁迫</span>
          </div>
          <div class="legend-item">
            <div class="legend-dot feature"></div>
            <span>特征</span>
          </div>
        </div>
        
        <div class="legend-help">
          <span>💡 默认展开到第三级。双击品种节点展开特征，右键收缩</span>
        </div>
      </div>
      
      <!-- 主要内容区域 - 左右布局 -->
      <div class="main-content">
        <!-- 左侧：图谱区域 -->
        <div class="graph-left">
          <div class="graph-main" v-loading="loading">
            <div id="knowledge-graph" ref="graphContainer"></div>
            
            <!-- 节点信息面板 -->
            <div class="node-info-panel" v-if="selectedNode" :style="panelStyle">
              <div class="panel-header">
                <h4>{{ selectedNode.name }}</h4>
                <el-button text @click="selectedNode = null">
                  <span>×</span>
                </el-button>
              </div>
              <div class="panel-content">
                <p><strong>类型:</strong> {{ getNodeTypeLabel(selectedNode.type) }}</p>
                <p v-if="selectedNode.level"><strong>层级:</strong> L{{ selectedNode.level }}</p>
                <p v-if="selectedNode.category">
                  <strong>分类:</strong> {{ selectedNode.category }}
                </p>
                <p v-if="selectedNode.description">
                  <strong>描述:</strong> {{ selectedNode.description }}
                </p>
                <p v-if="selectedNode.hasChildren">
                  <strong>状态:</strong> 
                  <el-tag :type="selectedNode.expanded ? 'success' : 'info'" size="small">
                    {{ selectedNode.expanded ? '已展开' : '可展开' }}
                  </el-tag>
                </p>
                
                <!-- 操作按钮 -->
                <div class="panel-actions">
                  <el-button 
                    v-if="selectedNode.type !== 'feature'" 
                    type="primary" 
                    size="small" 
                    @click="viewNodeDetail(selectedNode)">
                    查看详情
                  </el-button>
                  <el-button 
                    v-if="selectedNode.hasChildren && !selectedNode.expanded" 
                    type="success" 
                    size="small" 
                    @click="expandNode(selectedNode)">
                    展开子节点
                  </el-button>
                  <el-button 
                    v-if="selectedNode.hasChildren && selectedNode.expanded" 
                    type="warning" 
                    size="small" 
                    @click="collapseNode(selectedNode)">
                    收缩子节点
                  </el-button>
                </div>
              </div>
            </div>
          </div>
        </div>
        
        <!-- 右侧：数据统计和节点列表 -->
        <div class="graph-right">
          <!-- 数据统计 -->
          <el-card class="stats-card">
            <template #header>
              <h3>图谱数据统计</h3>
            </template>
            
            <div class="data-stats">
              <div class="stat-item">
                <span class="stat-label">节点数量：</span>
                <span class="stat-value">{{ graphData.nodes ? graphData.nodes.length : 0 }}</span>
              </div>
              <div class="stat-item">
                <span class="stat-label">关系数量：</span>
                <span class="stat-value">{{ graphData.links ? graphData.links.length : 0 }}</span>
              </div>
              <div class="stat-item">
                <span class="stat-label">L1作物：</span>
                <span class="stat-value crop">{{ getNodeCountByLevel(1) }}</span>
              </div>
              <div class="stat-item">
                <span class="stat-label">L2类型：</span>
                <span class="stat-value type">{{ getNodeCountByLevel(2) }}</span>
              </div>
              <div class="stat-item">
                <span class="stat-label">L3具体项：</span>
                <span class="stat-value variety">{{ getNodeCountByLevel(3) }}</span>
              </div>
              <div class="stat-item">
                <span class="stat-label">L4特征：</span>
                <span class="stat-value feature">{{ getNodeCountByLevel(4) }}</span>
              </div>
            </div>
          </el-card>

          <!-- 节点列表 -->
          <el-card class="nodes-card">
            <template #header>
              <h3>当前展示节点列表</h3>
            </template>
            
            <el-table :data="graphData.nodes" style="width: 100%" max-height="400">
              <el-table-column prop="name" label="节点名称" width="120" />
              <el-table-column prop="type" label="类型" width="80">
                <template #default="scope">
                  <el-tag :type="getTypeTagType(scope.row.type)" size="small">
                    {{ getNodeTypeLabel(scope.row.type) }}
                  </el-tag>
                </template>
              </el-table-column>
              <el-table-column prop="level" label="层级" width="60">
                <template #default="scope">
                  <el-tag size="small">L{{ scope.row.level }}</el-tag>
                </template>
              </el-table-column>
              <el-table-column label="状态" width="80">
                <template #default="scope">
                  <el-tag v-if="scope.row.hasChildren" :type="scope.row.expanded ? 'success' : 'info'" size="small">
                    {{ scope.row.expanded ? '已展开' : '可展开' }}
                  </el-tag>
                  <span v-else style="color: #999; font-size: 12px;">-</span>
                </template>
              </el-table-column>
              <el-table-column prop="description" label="描述" show-overflow-tooltip />
            </el-table>
            
            <div style="margin-top: 10px; text-align: center;" v-if="graphData.nodes && graphData.nodes.length > 0">
              <span style="color: #999; font-size: 12px;">
                当前展示 {{ graphData.nodes.length }} 个节点
              </span>
            </div>
          </el-card>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, nextTick, computed } from 'vue';
import { ElHeader, ElMenu, ElMenuItem, ElIcon, ElInput, ElButton, ElLink, ElCard, ElMessage, ElTable, ElTableColumn, ElTag } from 'element-plus';
import { User, Search, Lock, Unlock } from '@element-plus/icons-vue';
import { useRouter, useRoute } from 'vue-router';
import * as d3 from 'd3';

// 导入API函数
import { 
  getKnowledgeGraphData, 
  searchGraphNodes, 
  getSearchSuggestions, 
  getGraphNodeDetail,
  getNodeChildren // 🔥 新增：导入获取子节点的API
} from '@/api/agriculture/guo/knowledge/knowledgeGraph';

const router = useRouter();
const route = useRoute();

console.log('知识检索页面开始加载...');

// 响应式变量
const activeIndex = ref('4');
const searchKeyword = ref('');
const graphSearchKeyword = ref('');
const searching = ref(false);
const loading = ref(false);
const graphContainer = ref(null);
const graphData = ref({ nodes: [], links: [] });
const selectedNode = ref(null);
const panelStyle = ref({});
const selectedSuggestion = ref(null);

// 🔥 新增：展开状态管理
const expandedNodes = ref(new Set()); // 记录已展开的节点ID

// 🔥 新增：布局锁定状态
const layoutLocked = ref(true); // 默认锁定布局

/**
 * 🔥 新增：切换布局锁定状态
 */
const toggleLayoutLock = () => {
  layoutLocked.value = !layoutLocked.value;
  
  if (layoutLocked.value) {
    ElMessage.success('布局已锁定，节点位置固定');
    // 重新固定所有节点
    graphData.value.nodes.forEach(node => {
      if (node.x !== undefined && node.y !== undefined) {
        node.fx = node.x;
        node.fy = node.y;
        node.fixed = true;
      }
    });
  } else {
    ElMessage.info('布局已解锁，允许自由拖拽');
    // 解除固定状态（但保持当前位置）
    graphData.value.nodes.forEach(node => {
      node.fx = null;
      node.fy = null;
      node.fixed = false;
    });
  }
};

// D3相关变量
let svg = null;
let simulation = null;
let nodePositions = new Map();

const routerList = [  
  "",
  "CropIndex",           // 首页
  "CropVarietyFront",      // 作物品种
  "CropDiseasePest", // 病虫害
  "CropGraph",           // 图谱
  "QA"               // 问答
];

// 计算按层级统计的节点数量
const getNodeCountByLevel = (level) => {
  if (!graphData.value.nodes) return 0;
  return graphData.value.nodes.filter(node => node.level === level).length;
};

/**
 * 🔥 修复版：渲染D3图谱 - 解决点击后节点飞走问题
 */
const renderGraph = () => {
  console.log('开始渲染稳定图谱...');
  
  const validNodes = graphData.value.nodes.filter(node => node && node.id && node.name);
  const validNodeIds = new Set(validNodes.map(node => node.id));
  
  const validLinks = graphData.value.links.filter(link => {
    const sourceId = typeof link.source === 'string' ? link.source : (link.source?.id || link.source);
    const targetId = typeof link.target === 'string' ? link.target : (link.target?.id || link.target);
    
    if (!sourceId || !targetId) return false;
    if (!validNodeIds.has(sourceId) || !validNodeIds.has(targetId)) return false;
    
    return true;
  });
  
  console.log(`稳定渲染: ${validNodes.length}个节点, ${validLinks.length}个有效连接`);
  
  if (validNodes.length === 0) {
    console.warn('没有可显示的节点');
    return;
  }

  // 清除旧的SVG
  d3.select('#knowledge-graph').selectAll('*').remove();
  
  const container = document.getElementById('knowledge-graph');
  if (!container) {
    console.error('找不到图谱容器元素');
    return;
  }
  
  const width = container.clientWidth || 800;
  const height = container.clientHeight || 600;
  console.log('容器尺寸:', { width, height });
  
  // 创建SVG
  svg = d3.select('#knowledge-graph')
    .append('svg')
    .attr('width', width)
    .attr('height', height)
    .style('border', '1px solid #ccc')
    .call(d3.zoom()
      .scaleExtent([0.1, 4])
      .on('zoom', (event) => {
        g.attr('transform', event.transform);
      }));
  
  // 创建主要绘图区域
  const g = svg.append('g');
  
  // 🔥 保存并应用预设位置，同时记录固定状态
  const fixedNodes = new Set(); // 记录需要保持固定的节点
  validNodes.forEach(node => {
    if (node.fx !== undefined && node.fy !== undefined && node.fixed) {
      node.x = node.fx;
      node.y = node.fy;
      fixedNodes.add(node.id);
      console.log(`节点 ${node.name} 固定在位置: (${node.fx}, ${node.fy})`);
    }
  });
  
  // 处理连接数据
  const linksData = validLinks.map(link => ({
    source: typeof link.source === 'string' ? link.source : (link.source?.id || link.source),
    target: typeof link.target === 'string' ? link.target : (link.target?.id || link.target),
    type: link.type || '',
    label: link.label || ''
  }));
  
  // 🔥 创建静态布局 - 不使用力导向模拟以避免节点移动
  // 只有新展开的子节点才使用简单的力导向布局
  const newNodes = validNodes.filter(node => !node.fixed);
  
  if (newNodes.length > 0) {
    // 只对新节点使用轻微的力导向布局
    simulation = d3.forceSimulation(newNodes)
      .force('collision', d3.forceCollide().radius(d => getNodeRadius(d.type, d.level) + 10))
      .alpha(0.3)
      .alphaDecay(0.1)
      .velocityDecay(0.9);
      
    // 10秒后停止模拟，避免持续运动
    setTimeout(() => {
      if (simulation) {
        simulation.stop();
        // 将新节点也标记为固定
        newNodes.forEach(node => {
          node.fx = node.x;
          node.fy = node.y;
          node.fixed = true;
          fixedNodes.add(node.id);
        });
      }
    }, 2000);
  } else {
    // 如果没有新节点，不启动模拟
    simulation = null;
  }
  
  // 绘制连线
  const link = g.append('g')
    .attr('class', 'links')
    .selectAll('line')
    .data(linksData)
    .enter().append('line')
    .attr('stroke', '#999')
    .attr('stroke-opacity', 0.6)
    .attr('stroke-width', 2);
  
  // 绘制节点
  const node = g.append('g')
    .attr('class', 'nodes')
    .selectAll('g')
    .data(validNodes)
    .enter().append('g')
    .attr('class', 'node')
    .call(d3.drag()
      .on('start', (event, d) => dragstarted(event, d, fixedNodes))
      .on('drag', (event, d) => dragged(event, d, fixedNodes))
      .on('end', (event, d) => dragended(event, d, fixedNodes)));
  
  // 添加节点圆圈
  const circles = node.append('circle')
    .attr('r', d => getNodeRadius(d.type, d.level))
    .attr('fill', d => getNodeColor(d.type, d.level))
    .attr('stroke', '#fff')
    .attr('stroke-width', d => d.hasChildren ? 3 : 2) // 🔥 有子节点的边框更粗
    .style('cursor', 'pointer')
    .style('stroke-dasharray', d => d.hasChildren && !d.expanded ? '5,5' : 'none'); // 🔥 可展开节点使用虚线边框
  
  // 🔥 添加展开指示器
  node.filter(d => d.hasChildren && !d.expanded)
    .append('text')
    .attr('class', 'expand-indicator')
    .attr('text-anchor', 'middle')
    .attr('dy', '0.35em')
    .style('font-size', '12px')
    .style('font-weight', 'bold')
    .style('fill', '#fff')
    .style('pointer-events', 'none')
    .text('+');
  
  // 添加节点标签
  node.append('text')
    .attr('class', 'node-label')
    .attr('dy', d => d.hasChildren && !d.expanded ? '1.5em' : '0.35em') // 🔥 有指示器时标签下移
    .attr('text-anchor', 'middle')
    .style('font-size', d => getNodeFontSize(d.type, d.level))
    .style('font-weight', d => d.level === 1 ? 'bold' : 'normal')
    .style('fill', '#333')
    .style('pointer-events', 'none')
    .text(d => {
      const name = d.name || '未知';
      return name.length > 8 ? name.substring(0, 8) + '...' : name;
    });
  
  // 🔥 立即设置固定节点的初始位置
  validNodes.forEach(node => {
    if (fixedNodes.has(node.id)) {
      node.fx = node.x;
      node.fy = node.y;
    }
  });
  
  // 🔥 立即渲染固定节点的位置
  node.filter(d => fixedNodes.has(d.id))
    .attr('transform', d => `translate(${d.x || 0},${d.y || 0})`);
  
  link.filter(d => {
    const sourceId = typeof d.source === 'string' ? d.source : d.source.id;
    const targetId = typeof d.target === 'string' ? d.target : d.target.id;
    return fixedNodes.has(sourceId) && fixedNodes.has(targetId);
  })
  .attr('x1', d => {
    const sourceId = typeof d.source === 'string' ? d.source : d.source.id;
    const sourceNode = validNodes.find(n => n.id === sourceId);
    return sourceNode ? sourceNode.x : 0;
  })
  .attr('y1', d => {
    const sourceId = typeof d.source === 'string' ? d.source : d.source.id;
    const sourceNode = validNodes.find(n => n.id === sourceId);
    return sourceNode ? sourceNode.y : 0;
  })
  .attr('x2', d => {
    const targetId = typeof d.target === 'string' ? d.target : d.target.id;
    const targetNode = validNodes.find(n => n.id === targetId);
    return targetNode ? targetNode.x : 0;
  })
  .attr('y2', d => {
    const targetId = typeof d.target === 'string' ? d.target : d.target.id;
    const targetNode = validNodes.find(n => n.id === targetId);
    return targetNode ? targetNode.y : 0;
  });
  
  // 🔥 修改事件监听 - 防止点击时节点移动
  let clickTimer = null;
  node.on('click', (event, d) => {
    event.stopPropagation();
    
    // 🔥 阻止事件传播到拖拽处理
    event.sourceEvent?.stopPropagation();
    
    // 防止双击时触发单击
    if (clickTimer) {
      clearTimeout(clickTimer);
      clickTimer = null;
      return;
    }
    
    clickTimer = setTimeout(() => {
      selectNode(d, event);
      clickTimer = null;
    }, 250);
  })
  .on('dblclick', (event, d) => {
    event.stopPropagation();
    event.sourceEvent?.stopPropagation();
    
    // 清除单击定时器
    if (clickTimer) {
      clearTimeout(clickTimer);
      clickTimer = null;
    }
    
    // 🔥 双击展开子节点
    if (d.hasChildren && !d.expanded) {
      expandNode(d);
    } else if (d.hasChildren && d.expanded) {
      collapseNode(d);
    }
  })
  .on('contextmenu', (event, d) => {
    // 🔥 右键收缩节点
    event.preventDefault();
    event.stopPropagation();
    if (d.hasChildren && d.expanded) {
      collapseNode(d);
    }
  });
  
  // 🔥 只对新节点更新模拟
  if (simulation) {
    simulation.on('tick', () => {
      // 只更新新节点的连线
      link
        .attr('x1', d => {
          const source = typeof d.source === 'object' ? d.source : validNodes.find(n => n.id === d.source);
          return source ? source.x : 0;
        })
        .attr('y1', d => {
          const source = typeof d.source === 'object' ? d.source : validNodes.find(n => n.id === d.source);
          return source ? source.y : 0;
        })
        .attr('x2', d => {
          const target = typeof d.target === 'object' ? d.target : validNodes.find(n => n.id === d.target);
          return target ? target.x : 0;
        })
        .attr('y2', d => {
          const target = typeof d.target === 'object' ? d.target : validNodes.find(n => n.id === d.target);
          return target ? target.y : 0;
        });
      
      // 只更新新节点的位置
      node.filter(d => !fixedNodes.has(d.id))
        .attr('transform', d => `translate(${d.x || 0},${d.y || 0})`);
    });
  }
  
  // 点击空白处取消选择
  svg.on('click', () => {
    selectedNode.value = null;
  });
  
  console.log('稳定D3图谱渲染完成，固定节点数:', fixedNodes.size);
};

/**
 * 🔥 修改：展开节点功能 - 确保子节点也能稳定显示
 */
const expandNode = async (node) => {
  if (!node.hasChildren || node.expanded) {
    console.log('节点无法展开:', node);
    return;
  }
  
  try {
    loading.value = true;
    console.log('开始展开节点:', node.id);
    
    const response = await getNodeChildren(node.id);
    
    if (response.code === 200 && response.data) {
      const children = response.data.nodes || [];
      const childLinks = response.data.links || [];
      
      console.log(`获取到 ${children.length} 个子节点`);
      
      if (children.length === 0) {
        ElMessage.info('该节点没有子节点');
        return;
      }
      
      // 🔥 为子节点设置稳定的布局位置
      const parentX = node.x || node.fx || 400;
      const parentY = node.y || node.fy || 300;
      const childRadius = 60; // 子节点环形半径
      
      children.forEach((child, index) => {
        const angle = (2 * Math.PI * index) / children.length;
        const x = parentX + childRadius * Math.cos(angle);
        const y = parentY + childRadius * Math.sin(angle);
        
        // 🔥 设置子节点为固定位置
        child.x = x;
        child.y = y;
        child.fx = x;
        child.fy = y;
        child.fixed = true; // 标记为固定节点
        child.parentNodeId = node.id; // 标记父节点
        
        console.log(`子节点 ${child.name} 固定在位置: (${x}, ${y})`);
      });
      
      // 更新图谱数据
      graphData.value.nodes.push(...children);
      graphData.value.links.push(...childLinks);
      
      // 标记节点为已展开
      node.expanded = true;
      expandedNodes.value.add(node.id);
      
      // 重新渲染图谱
      nextTick(() => {
        renderGraph();
      });
      
      ElMessage.success(`已展开 ${children.length} 个子节点`);
      
    } else {
      ElMessage.error('获取子节点失败：' + (response.msg || '未知错误'));
    }
  } catch (error) {
    console.error('展开节点失败:', error);
    ElMessage.error('展开节点失败');
  } finally {
    loading.value = false;
  }
};

/**
 * 🔥 新增：收缩节点功能
 */
const collapseNode = (node) => {
  if (!node.hasChildren || !node.expanded) {
    console.log('节点无法收缩:', node);
    return;
  }
  
  console.log('开始收缩节点:', node.id);
  
  // 移除子节点及其连线
  const childNodeIds = graphData.value.nodes
    .filter(n => n.parentNodeId === node.id)
    .map(n => n.id);
  
  console.log('要移除的子节点:', childNodeIds);
  
  // 移除子节点
  graphData.value.nodes = graphData.value.nodes.filter(n => !childNodeIds.includes(n.id));
  
  // 移除相关连线
  graphData.value.links = graphData.value.links.filter(link => {
    const sourceId = typeof link.source === 'string' ? link.source : (link.source?.id || link.source);
    const targetId = typeof link.target === 'string' ? link.target : (link.target?.id || link.target);
    return !childNodeIds.includes(sourceId) && !childNodeIds.includes(targetId);
  });
  
  // 标记节点为未展开
  node.expanded = false;
  expandedNodes.value.delete(node.id);
  
  // 重新渲染图谱
  nextTick(() => {
    renderGraph();
  });
  
  ElMessage.success(`已收缩 ${childNodeIds.length} 个子节点`);
};

/**
 * 🔥 新增：收缩所有已展开的节点
 */
const collapseAllNodes = () => {
  const expandedNodesList = graphData.value.nodes.filter(node => node.expanded);
  
  if (expandedNodesList.length === 0) {
    ElMessage.info('没有已展开的节点');
    return;
  }
  
  expandedNodesList.forEach(node => {
    collapseNode(node);
  });
  
  ElMessage.success(`已收缩 ${expandedNodesList.length} 个节点`);
};

/**
 * 页面导航处理
 */
const handleSelect = (key) => { 
  activeIndex.value = key;
  const routeName = routerList[key];
  router.push({ name: routeName }); 
};

/**
 * 顶部搜索框搜索
 */
const onSearch = () => { 
  console.log('关键词:', searchKeyword.value);
  graphSearchKeyword.value = searchKeyword.value;
  handleGraphSearch();
};

/**
 * 设置关键词并搜索
 */
const setKeyword = (word) => {
  searchKeyword.value = word;
  onSearch();
};

/**
 * 重置图谱到初始状态
 */
const resetGraph = () => {
  selectedNode.value = null;
  nodePositions.clear();
  expandedNodes.value.clear(); // 🔥 清除展开状态
  nextTick(() => {
    loadGraphData('crop_1');
  });
  ElMessage.success('图谱已重置到初始状态');
};

/**
 * 初始化图谱
 */
const initGraph = async () => {
  loading.value = true;
  try {
    console.log('开始加载图谱数据...');
    
    const urlSearchKeyword = route.query.searchKeyword;
    if (urlSearchKeyword) {
      console.log('从URL获取搜索关键词:', urlSearchKeyword);
      searchKeyword.value = urlSearchKeyword;
      graphSearchKeyword.value = urlSearchKeyword;
      await handleGraphSearchWithKeyword(urlSearchKeyword);
    } else {
      await loadGraphData('crop_1');
    }
    
    console.log('图谱数据加载完成');
  } catch (error) {
    console.error('初始化图谱失败:', error);
    ElMessage.error('初始化图谱失败');
  } finally {
    loading.value = false;
  }
};

/**
 * 使用关键词搜索图谱
 */
const handleGraphSearchWithKeyword = async (keyword) => {
  try {
    console.log('使用关键词搜索图谱:', keyword);
    const response = await searchGraphNodes(keyword);
    console.log('搜索结果:', response);
    
    if (response.code === 200 && response.data && response.data.centerNode) {
      await loadGraphData(response.data.centerNode);
      
      const searchType = response.data.searchType || 'crop';
      if (searchType === 'variety') {
        ElMessage.success(`已找到品种"${response.data.keyword}"并切换到对应的知识图谱`);
      } else {
        ElMessage.success(`已切换到${response.data.keyword}的知识图谱`);
      }
    } else {
      await loadGraphData('crop_1');
      ElMessage.warning(response.msg || '未找到相关节点，已加载默认图谱');
    }
  } catch (error) {
    console.error('搜索失败:', error);
    await loadGraphData('crop_1');
    ElMessage.error('搜索失败，已加载默认图谱');
  }
};

/**
 * 🔥 优化版：加载图谱数据（包含预设布局）
 */
const loadGraphData = async (centerNode = 'crop_1') => {
  try {
    console.log('请求图谱数据，中心节点:', centerNode);
    const response = await getKnowledgeGraphData(centerNode);
    console.log('获取到的原始数据:', response);
    
    if (response.code === 200) {
      graphData.value = {
        nodes: response.data.nodes || [],
        links: response.data.links || []
      };
      
      // 🔥 清除展开状态
      expandedNodes.value.clear();
      
      console.log('数据详情:', {
        nodes: graphData.value.nodes.length,
        links: graphData.value.links.length
      });
      
      ElMessage.success(`图谱数据加载成功：${graphData.value.nodes.length}个节点（优化布局）`);
      
      // 重置状态
      selectedNode.value = null;
      nodePositions.clear();
      
      // 渲染D3图谱
      nextTick(() => {
        console.log('准备渲染优化图谱');
        renderGraph();
      });
    } else {
      ElMessage.error('获取图谱数据失败：' + response.msg);
    }
  } catch (error) {
    console.error('加载图谱数据失败:', error);
    ElMessage.error('加载图谱数据失败');
    throw error;
  }
};

/**
 * 获取节点半径
 */
const getNodeRadius = (type, level) => {
  const levelRadiusMap = {
    1: 28,  // L1 作物 - 最大
    2: 22,  // L2 类型 - 大
    3: 18,  // L3 具体项 - 中
    4: 14   // L4 特征 - 小
  };
  
  return levelRadiusMap[level] || 18;
};

/**
 * 获取节点颜色
 */
const getNodeColor = (type, level) => {
  if (level === 1) return '#ff4d4f'; // L1 作物 - 红色
  if (level === 2) return '#1890ff'; // L2 类型 - 蓝色
  
  if (level === 3) {
    const typeColorMap = {
      'variety': '#13c2c2',   // 品种 - 青色
      'disease': '#ff9c6e',   // 病害 - 橙色
      'pest': '#fadb14',      // 虫害 - 黄色
      'stress': '#b37feb'     // 非生物胁迫 - 紫色
    };
    return typeColorMap[type] || '#52c41a'; // 默认绿色
  }
  
  if (level === 4) return '#52c41a'; // L4 特征 - 绿色
  
  // 兼容性处理
  const typeColorMap = {
    'crop': '#ff4d4f',      // 作物 - 红色
    'variety_type': '#1890ff', // 品种类型 - 蓝色
    'disease_type': '#1890ff', // 病害类型 - 蓝色
    'pest_type': '#1890ff',    // 虫害类型 - 蓝色
    'stress_type': '#1890ff',  // 胁迫类型 - 蓝色
    'variety': '#13c2c2',      // 品种 - 青色
    'disease': '#ff9c6e',      // 病害 - 橙色
    'pest': '#fadb14',         // 虫害 - 黄色
    'stress': '#b37feb',       // 胁迫 - 紫色
    'feature': '#52c41a'       // 特征 - 绿色
  };
  return typeColorMap[type] || '#8c8c8c';
};

/**
 * 获取节点字体大小
 */
const getNodeFontSize = (type, level) => {
  const levelSizeMap = {
    1: '15px',  // L1 作物
    2: '13px',  // L2 类型
    3: '12px',  // L3 具体项
    4: '10px'   // L4 特征
  };
  
  return levelSizeMap[level] || '12px';
};

/**
 * 选中节点
 */
const selectNode = (node, event) => {
  selectedNode.value = node;
  console.log('选中节点:', node);
  
  panelStyle.value = {
    position: 'fixed',
    left: (event.clientX + 10) + 'px',
    top: (event.clientY - 50) + 'px',
    zIndex: 1000
  };
};

/**
 * 获取节点类型标签
 */
const getNodeTypeLabel = (type) => {
  const labelMap = {
    'crop': '作物',
    'variety_type': '品种类型',
    'disease_type': '病害类型', 
    'pest_type': '虫害类型',
    'stress_type': '胁迫类型',
    'variety': '品种',
    'disease': '病害',
    'pest': '虫害',
    'stress': '非生物胁迫',
    'feature': '特征'
  };
  return labelMap[type] || type || '未知';
};

/**
 * 获取标签类型样式
 */
const getTypeTagType = (type) => {
  const typeMap = {
    'crop': 'danger',
    'variety_type': 'primary',
    'disease_type': 'primary',
    'pest_type': 'primary', 
    'stress_type': 'primary',
    'variety': 'info',
    'disease': 'warning',
    'pest': 'warning',
    'stress': 'info',
    'feature': 'success'
  };
  return typeMap[type] || 'info';
};

/**
 * 获取搜索建议
 */
const querySearchSuggestions = async (queryString, callback) => {
  if (!queryString || queryString.length < 1) {
    callback([]);
    return;
  }
  
  try {
    const response = await getSearchSuggestions(queryString);
    if (response.code === 200) {
      callback(response.data || []);
    } else {
      callback([]);
    }
  } catch (error) {
    console.error('获取搜索建议失败:', error);
    callback([]);
  }
};

/**
 * 处理搜索建议选择
 */
const handleSuggestionSelect = (item) => {
  console.log('选择搜索建议:', item);
  selectedSuggestion.value = item;
  graphSearchKeyword.value = item.name;
  handleGraphSearchWithNode(item.id);
};

/**
 * 使用指定节点ID搜索
 */
const handleGraphSearchWithNode = async (nodeId) => {
  searching.value = true;
  try {
    console.log('使用节点ID搜索:', nodeId);
    const response = await searchGraphNodes(graphSearchKeyword.value, nodeId);
    console.log('搜索结果:', response);
    
    if (response.code === 200 && response.data && response.data.centerNode) {
      await loadGraphData(response.data.centerNode);
      
      const searchType = response.data.searchType || 'crop';
      if (searchType === 'variety') {
        ElMessage.success(`已切换到品种"${graphSearchKeyword.value}"的知识图谱`);
      } else {
        ElMessage.success(`已切换到${graphSearchKeyword.value}的知识图谱`);
      }
    } else {
      ElMessage.warning(response.msg || '搜索失败');
    }
  } catch (error) {
    console.error('搜索失败:', error);
    ElMessage.error('搜索失败');
  } finally {
    searching.value = false;
  }
};

/**
 * 获取建议项标签类型
 */
const getSuggestionTagType = (type) => {
  const typeMap = {
    'crop': 'danger',
    'variety': 'primary',
    'disease': 'warning',
    'pest': 'warning',
    'feature': 'success'
  };
  return typeMap[type] || '';
};

/**
 * 获取建议项类型标签
 */
const getSuggestionTypeLabel = (type) => {
  const labelMap = {
    'crop': '作物',
    'variety': '品种',
    'disease': '病害',
    'pest': '虫害',
    'feature': '特征'
  };
  return labelMap[type] || type;
};

/**
 * 🔥 修复：查看节点详情 - 确保正确跳转到象差百科
 */
const viewNodeDetail = (node) => {
  console.log('查看节点详情:', node);
  
  try {
    // 🔥 根据节点类型和名称确定跳转逻辑
    if (node.type === 'variety') {
      // 品种节点 -> 跳转到标准象百科
      router.push({ 
        name: 'cropVarietyFront', 
        query: { 
          varietyId: node.id, 
          varietyName: node.name 
        } 
      });
    } else if (['disease_type', 'pest_type', 'stress_type'].includes(node.type)) {
      // 🔥 病害类型、虫害类型、胁迫类型节点 -> 跳转到象差百科并自动筛选
      let cropType = ''; // 作物类型
      let categoryType = ''; // 分类类型
      
      // 从节点名称中提取作物类型
      if (node.name.includes('小麦')) {
        cropType = '小麦';
      } else if (node.name.includes('玉米')) {
        cropType = '玉米';
      }
      
      // 根据节点类型确定分类
      if (node.type === 'disease_type') {
        categoryType = '病害';
      } else if (node.type === 'pest_type') {
        categoryType = '虫害';
      } else if (node.type === 'stress_type') {
        categoryType = '非生物胁迫';
      }
      
      console.log('🎯 跳转参数:', { cropType, categoryType });
      
      // 🔥 跳转到象差百科页面 - 使用修复后的路由名称
      router.push({ 
        name: 'CropDiseasePest',  // 使用name而不是path，确保路由正确
        query: {
          crop: cropType,
          category: categoryType,
          autoSearch: 'true' // 标记为自动搜索
        }
      });
      
      ElMessage.success(`正在查看${cropType}${categoryType}详情...`);
      
    } else if (['disease', 'pest', 'stress'].includes(node.type)) {
      // 🔥 具体的病害、虫害、胁迫节点 -> 跳转到详情页面
      router.push({
        path: '/pest-disease-detail',
        query: {
          name: node.name,
          type: getNodeTypeLabel(node.type)
        }
      });
    } else if (node.type === 'crop') {
      // 作物节点 -> 跳转到标准象百科
      router.push({ 
        name: 'cropVarietyFront', 
        query: { 
          cropId: node.id, 
          cropName: node.name 
        } 
      });
    } else {
      // 其他节点类型
      ElMessage.info(`${node.name} - ${getNodeTypeLabel(node.type)}节点暂无详情页面`);
    }
  } catch (error) {
    console.error('页面跳转失败:', error);
    ElMessage.error('页面跳转失败，请检查路由配置');
  }
};

// 🔥 修改拖拽相关函数 - 考虑布局锁定状态
const dragstarted = (event, d, fixedNodes) => {
  // 🔥 如果布局被锁定，不允许拖拽
  if (layoutLocked.value) {
    console.log(`布局已锁定，禁止拖拽节点 ${d.name}`);
    return;
  }
  
  // 🔥 如果是固定节点且布局未解锁，不允许拖拽
  if (fixedNodes && fixedNodes.has(d.id)) {
    console.log(`节点 ${d.name} 是固定节点，禁止拖拽`);
    return;
  }
  
  if (simulation && !event.active) {
    simulation.alphaTarget(0.3).restart();
  }
  d.fx = d.x;
  d.fy = d.y;
};

const dragged = (event, d, fixedNodes) => {
  // 🔥 如果布局被锁定，不允许拖拽
  if (layoutLocked.value) {
    return;
  }
  
  // 🔥 如果是固定节点且布局未解锁，不允许拖拽
  if (fixedNodes && fixedNodes.has(d.id)) {
    return;
  }
  
  d.fx = event.x;
  d.fy = event.y;
};

const dragended = (event, d, fixedNodes) => {
  // 🔥 如果布局被锁定，不允许拖拽
  if (layoutLocked.value) {
    return;
  }
  
  // 🔥 如果是固定节点且布局未解锁，不允许拖拽
  if (fixedNodes && fixedNodes.has(d.id)) {
    return;
  }
  
  if (simulation && !event.active) {
    simulation.alphaTarget(0);
  }
  
  // 🔥 保存新节点的位置
  nodePositions.set(d.id, { x: d.x, y: d.y });
  
  // 🔥 拖拽结束后固定新位置（如果布局解锁状态下）
  if (!layoutLocked.value) {
    d.fx = d.x;
    d.fy = d.y;
  }
};

/**
 * 图谱搜索处理
 */
const handleGraphSearch = async () => {
  if (!graphSearchKeyword.value.trim()) {
    ElMessage.warning('请输入搜索关键词');
    return;
  }
  
  if (selectedSuggestion.value && selectedSuggestion.value.name === graphSearchKeyword.value) {
    await handleGraphSearchWithNode(selectedSuggestion.value.id);
    return;
  }
  
  searching.value = true;
  try {
    console.log('搜索关键词:', graphSearchKeyword.value);
    const response = await searchGraphNodes(graphSearchKeyword.value);
    console.log('搜索结果:', response);
    
    if (response.code === 200 && response.data && response.data.centerNode) {
      await loadGraphData(response.data.centerNode);
      
      const searchType = response.data.searchType || 'crop';
      if (searchType === 'variety') {
        ElMessage.success(`已找到品种"${response.data.keyword}"并切换到对应的知识图谱`);
      } else {
        ElMessage.success(`已切换到${response.data.keyword}的知识图谱`);
      }
    } else {
      ElMessage.warning(response.msg || '未找到相关节点，请尝试搜索作物名称（如：小麦、玉米）或品种名称');
    }
  } catch (error) {
    console.error('搜索失败:', error);
    ElMessage.error('搜索失败');
  } finally {
    searching.value = false;
  }
};

// 生命周期
onMounted(() => {
  console.log('组件已挂载，开始初始化...');
  nextTick(() => {
    initGraph();
  });
});

console.log('知识检索页面加载完成');
</script>

<style scoped>
/* 保持原有样式，新增优化样式 */
.custom-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0 30px;
  height: 60px;
  background: linear-gradient(90deg, #1bbc9b, #17c2e6);
  color: #fff;
  font-size: 18px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.logo-title {
  font-weight: bold;
  font-size: 22px;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 16px;
}

.custom-menu {
  border-bottom: 1px solid #e0e0e0;
  padding: 0 30px;
  font-size: 16px;
}

.search-section {
  text-align: center;
  padding: 30px 20px;
  background-color: #f9f9f9;
}

.headline {
  font-size: 22px;
  font-weight: bold;
  margin-bottom: 20px;
}

.search-bar {
  display: flex;
  justify-content: center;
  align-items: center;
  margin-bottom: 15px;
  flex-wrap: wrap;
  gap: 10px;
}

.search-input {
  width: 60vw;
  height: 50px;
}

.hot-words {
  font-size: 14px;
  color: #666;
}

.hot-words .el-link {
  margin-left: 10px;
}

.knowledge-graph-container {
  padding: 20px;
  display: flex;
  flex-direction: column;
  background: #f0f2f5;
  min-height: calc(100vh - 300px);
}

.graph-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 24px;
  background: white;
  border-radius: 8px;
  margin-bottom: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.toolbar-left {
  display: flex;
  align-items: center;
  gap: 12px;
}

.search-container {
  display: flex;
  align-items: center;
  gap: 12px;
}

.suggestion-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 4px 0;
}

.suggestion-main {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.suggestion-name {
  font-weight: 500;
  color: #333;
}

.suggestion-desc {
  font-size: 12px;
  color: #999;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: 12px;
}

.graph-legend {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 24px;
  background: white;
  border-radius: 8px;
  margin-bottom: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.legend-left {
  display: flex;
  align-items: center;
  gap: 15px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: #666;
}

.legend-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
}

.legend-dot.crop {
  background: #ff4d4f; /* 红色 */
}

.legend-dot.type {
  background: #1890ff; /* 蓝色 */
}

.legend-dot.variety {
  background: #13c2c2; /* 青色 */
}

.legend-dot.disease {
  background: #ff9c6e; /* 橙色 */
}

.legend-dot.pest {
  background: #fadb14; /* 黄色 */
}

.legend-dot.stress {
  background: #b37feb; /* 紫色 */
}

.legend-dot.feature {
  background: #52c41a; /* 绿色 */
}

.legend-help {
  font-size: 12px;
  color: #999;
}

.main-content {
  display: flex;
  gap: 20px;
  flex: 1;
}

.graph-left {
  flex: 1;
  min-width: 0;
}

.graph-main {
  background: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  position: relative;
  height: 600px;
}

#knowledge-graph {
  width: 100%;
  height: 100%;
  border: 1px solid #e8e8e8;
  border-radius: 4px;
  background: #fafafa;
  cursor: grab;
}

#knowledge-graph:active {
  cursor: grabbing;
}

.graph-right {
  width: 350px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.stats-card {
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.nodes-card {
  flex: 1;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.data-stats {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.stat-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 0;
  border-bottom: 1px solid #f0f0f0;
}

.stat-item:last-child {
  border-bottom: none;
}

.stat-label {
  font-size: 14px;
  color: #666;
}

.stat-value {
  font-size: 16px;
  font-weight: bold;
  color: #333;
}

.stat-value.crop {
  color: #ff4d4f;
}

.stat-value.type {
  color: #1890ff;
}

.stat-value.variety {
  color: #13c2c2;
}

.stat-value.feature {
  color: #52c41a;
}

.node-info-panel {
  background: white;
  border: 1px solid #d9d9d9;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  padding: 16px;
  min-width: 200px;
  max-width: 300px;
}

.panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid #f0f0f0;
}

.panel-header h4 {
  margin: 0;
  color: #333;
  font-size: 14px;
}

.panel-content p {
  margin: 8px 0;
  font-size: 12px;
  color: #666;
  line-height: 1.4;
}

.panel-actions {
  margin-top: 12px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

/* 🔥 新增：节点展开指示器样式 */
:deep(.expand-indicator) {
  font-family: monospace;
  font-size: 12px !important;
  font-weight: bold !important;
  fill: #fff !important;
}

:deep(.node-label) {
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

/* D3.js 相关样式 */
:deep(.links line) {
  stroke: #999;
  stroke-opacity: 0.6;
}

:deep(.nodes circle) {
  cursor: pointer;
  transition: all 0.3s ease;
}

:deep(.nodes circle:hover) {
  stroke-width: 4px;
  filter: brightness(1.1);
}

:deep(.nodes text) {
  pointer-events: none;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

/* 🔥 新增：虚线边框动画效果 */
:deep(.nodes circle[stroke-dasharray]) {
  animation: dash 2s linear infinite;
}

@keyframes dash {
  to {
    stroke-dashoffset: -10;
  }
}

/* 响应式设计 */
@media (max-width: 1200px) {
  .main-content {
    flex-direction: column;
  }
  
  .graph-right {
    width: 100%;
  }
  
  .data-stats {
    flex-direction: row;
    flex-wrap: wrap;
  }
  
  .stat-item {
    flex: 1;
    min-width: 150px;
    border-bottom: none;
    border-right: 1px solid #f0f0f0;
    padding: 8px 12px;
  }
  
  .stat-item:last-child {
    border-right: none;
  }
}
</style>